//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//********************************************************* 

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Windows.Forms;

namespace Microsoft.TridentWordAddIn.Presentation
{
    public partial class WatermarkTextBox : TextBox
    {
        private static uint EcmFirst = 0x1500;
        private static uint EmSetCueBanner = EcmFirst + 1;
        private bool showCueTextWithFocus;
        private string cueText = string.Empty;

        /// <summary>
        /// Initializes a new instance of the <see cref="WatermarkTextBox"/> class.
        /// </summary>
        public WatermarkTextBox()
        {
            this.InitializeComponent();
        }

        /// <summary>
        /// Occurs when the <see cref="CueText"/> property value changes.
        /// </summary>
        public event EventHandler CueTextChanged;

        /// <summary>
        /// Raises the <see cref="E:CueTextChanged"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        protected virtual void OnCueTextChanged(EventArgs e)
        {
            EventHandler handler = this.CueTextChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        /// <summary>
        /// Sends the message.
        /// </summary>
        /// <param name="handle">The handle.</param>
        /// <param name="message">The message.</param>
        /// <param name="wParam">The w param.</param>
        /// <param name="lParam">The l param.</param>
        /// <returns>IntPtr</returns>
        [DllImport("user32.dll", CharSet = CharSet.Unicode, SetLastError = false)]
        private static extern IntPtr SendMessage(HandleRef handle, uint message, IntPtr wParam, string lParam);

        #region CueText

        /// <summary>
        /// Gets or sets the text the <see cref="TextBox"/> will display as a cue to the user.
        /// </summary>
        [Description("The text value to be displayed as a cue to the user.")]
        [Category("Appearance")]
        [DefaultValue("")]
        [Localizable(true)]
        public string CueText
        {
            get
            {
                return this.cueText; 
            }

            set
            {
                if (value == null)
                {
                    value = String.Empty;
                }

                if (!this.cueText.Equals(value, StringComparison.CurrentCulture))
                {
                    this.cueText = value;
                    this.UpdateCue();
                    this.OnCueTextChanged(EventArgs.Empty);
                }
            }
        }

        #endregion CueText

        #region ShowCueTextOnFocus

        /// <summary>
        /// Gets or sets a value indicating whether the <see cref="TextBox"/> will display the <see cref="CueText"/>
        /// even when the control has focus.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [show cue text with focus]; otherwise, <c>false</c>.
        /// </value>
        [Description("Indicates whether the CueText will be displayed even when the control has focus.")]
        [Category("Appearance")]
        [DefaultValue(false)]
        [Localizable(true)]
        public bool ShowCueTextWithFocus
        {
            get 
            {
                return this.showCueTextWithFocus; 
            }

            set
            {
                if (this.showCueTextWithFocus != value)
                {
                    this.showCueTextWithFocus = value;
                    this.UpdateCue();
                    this.OnShowCueTextWithFocusChanged(EventArgs.Empty);
                }
            }
        }

        /// <summary>
        /// Occurs when the <see cref="ShowCueTextWithFocus"/> property value changes.
        /// </summary>
        public event EventHandler ShowCueTextWithFocusChanged;

        /// <summary>
        /// Raises the <see cref="E:ShowCueTextWithFocusChanged"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        [EditorBrowsable(EditorBrowsableState.Advanced)]
        protected virtual void OnShowCueTextWithFocusChanged(EventArgs e)
        {
            EventHandler handler = this.ShowCueTextWithFocusChanged;
            if (handler != null)
            {
                handler(this, e);
            }
        }

        #endregion ShowCueTextOnFocus

        #region Overrides

        /// <summary>
        /// On Text Box Creation
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected override void OnHandleCreated(EventArgs e)
        {
            this.UpdateCue();
            base.OnHandleCreated(e);
        }

        #endregion Overrides

        /// <summary>
        /// Updates the cue.
        /// </summary>
        private void UpdateCue()
        {
            // If the handle isn't yet created, 
            // this will be called when it is created
            if (this.IsHandleCreated)
            {
                SendMessage(new HandleRef(this, this.Handle), EmSetCueBanner, this.showCueTextWithFocus ? new IntPtr(1) : IntPtr.Zero, this.cueText);
            }
        }
    }
}
